package com.gyj.register;

import com.gyj.register.entity.HeartBeatRequest;
import com.gyj.register.entity.HeartBeatResponse;
import com.gyj.register.entity.RegisterRequest;
import com.gyj.register.entity.RegisterResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.UUID;

/**
 * 在服务上创建和启动，负责跟register-server进行通信
 * @author Gao
 * @date 2021/6/26
 */
public class RegisterClient {

    private static final Logger logger = LogManager.getLogger(RegisterClient.class);

    public static final String SERVICE_NAME = "inventory-service";
    public static final String IP = "192.168.31.207";
    public static final String HOSTNAME = "inventory01";
    public static final int PORT = 9000;
    private static final Long HEARTBEAT_INTERVAL = 30 * 1000L;

    /**
     * 服务实例id
     */
    private String serviceInstanceId;
    /**
     * http通信组件
     */
    private HttpSender httpSender;
    /**
     * 发送注册信息的组件
     */
    private RegisterWorker registerWorker;
    /**
     * 心跳线程
     */
    private HeartBeatWorker heartBeatWorker;
    /**
     * 服务实例是否在运行
     * volatile保证线程间对共享变量的可见性
     */
    private volatile boolean isRunning;

    /**
     * 客户端缓存的注册表
     */
    private CachedServiceRegistry registry;

    public RegisterClient() {
        this.serviceInstanceId = UUID.randomUUID().toString().replace("-", "");
        this.httpSender = new HttpSender();
        this.heartBeatWorker = new HeartBeatWorker();
        this.registerWorker = new RegisterWorker();
        this.isRunning = true;
        // 初始化缓存注册表
        this.registry = new CachedServiceRegistry(this, httpSender);
    }

    /**
     * 启动客户端RegisterClient组件
     */
    public void start() {
        // 客户端启动主要逻辑：
        // 1.开启一个线程去register-server去发送请求，注册这个服务
        // 2.注册成功之后，会开启一个发送心跳的定时任务，每隔默认30s
        // 3.注册成功之后，开启定时拉取服务注册表的定时任务，默认30s
        try {
            registerWorker.start();
            registerWorker.join();
            // 启动发送线条的线程组件
            heartBeatWorker.start();
            // 初始化服务注册表拉取的组件
            registry.initialize();
        } catch (InterruptedException e) {
            logger.error("客户端RegisterClient启动异常e:{}", e);
        }
    }

    /**
     * 停止客户端组件
     */
    public void shutDown() {
        // volatile状态标志位停止线程的执行
        this.isRunning = false;
        // 终止定时发送心跳的定时任务
        this.heartBeatWorker.interrupt();
        // 终止定时拉取注册表的线程
        this.registry.destroy();
        // 当前服务实例下线
        this.httpSender.cancel(SERVICE_NAME, serviceInstanceId);
    }

    /**
     * 服务注册线程
     */
    private class RegisterWorker extends Thread {
        @Override
        public void run() {
            RegisterRequest request = new RegisterRequest();
            request.setServiceName(SERVICE_NAME);
            request.setServiceInstanceId(serviceInstanceId);
            request.setIp(IP);
            request.setHostName(HOSTNAME);
            request.setPort(PORT);
            logger.info("服务注册线程发送本机注册，参数request:{}", request);
            // 发起注册请求
            RegisterResponse response = httpSender.register(request);
            logger.info("服务注册线程发送本机注册, 返回结果response:{}", response);
        }
    }

    /**
     * 定时发送心跳线程的定时任务
     */
    private class HeartBeatWorker extends Thread {
        @Override
        public void run() {
            HeartBeatRequest request = new HeartBeatRequest();
            request.setServiceName(SERVICE_NAME);
            request.setServiceInstanceId(serviceInstanceId);
            HeartBeatResponse response;
            while (isRunning) {
                try {
                    response = httpSender.heartBeat(request);
                    logger.info("心跳线程返回response:{}", response);
                    Thread.sleep(HEARTBEAT_INTERVAL);
                } catch (Exception e) {
                    logger.error("心跳线程异常e:{}", e);
                }
            }
        }
    }

    /**
     * 获取判断服务是否正在运行的变量
     * @return
     */
    public boolean isRunning() {
        return isRunning;
    }
}
